home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: comp.lang.c++
- Path: BALROG.NCI.NIH.GOV!SYSTEX
- From: systex@BALROG.NCI.NIH.GOV (Donald G. Plugge, Systex Inc., (301)210-7701)
- Subject: VMS Descriptor Class
- Message-ID: <1996Feb27.170009.15649@alw.nih.gov>
- Sender: postman@alw.nih.gov (AMDS Postmaster)
- Nntp-Posting-Host: balrog.nci.nih.gov
- Reply-To: systex@BALROG.NCI.NIH.GOV
- Organization: Organization, City, State, etc.
- Date: Tue, 27 Feb 1996 17:00:09 GMT
-
- >
- >
- >
- > In the spirit of object oriented programming, I'd like to ask a design question
- > in order to determine which C++ component to utilize in a particular case. I
- > have experience with C, however, I have just begun to explore the vast
- > assortment of features available in C++. My questions concerns the string
- > class and whether to include, cast or inherit them into another structure.
- >
- > My coding is done on an Alpha 3400 running VMS 6.1 with DEC C++ version 3.1.
- > In the VMS environment system service calls use a structure called a descriptor
- > to pass character data. The definition of the structure is contained in the
- > <descrip.h> file. The relevant section follows below. Notice that the code
- > #defines a $DESCRIPTOR macro to place an array of characters into the
- > descriptor structure. The new descriptor is then ready to be passed to the
- > system service.
- >
- > /*
- > * Fixed-Length Descriptor:
- > */
- > struct dsc$descriptor_s
- > {
- > unsigned short dsc$w_length; /* length of data item in bytes,
- > or if dsc$b_dtype is DSC$K_DTYPE_V, bits,
- > or if dsc$b_dtype is DSC$K_DTYPE_P, digits (4 bits each) */
- > unsigned char dsc$b_dtype; /* data type code */
- > unsigned char dsc$b_class; /* descriptor class code = DSC$K_CLASS_S */
- > char *dsc$a_pointer; /* address of first byte of data storage */
- > };
- >
- > /*
- > * A simple macro to construct a string descriptor:
- > */
- > #define $DESCRIPTOR(name,string) struct dsc$descriptor_s name = { sizeof(string)-1, DSC$K_DTYPE_T, DSC$K_CLASS_S, string }
- >
- > An example of a call to the macro would be:
- >
- > dsc$descriptor_s dsc;
- > $DESCRIPTOR(dsc, "XYZ");
- > status = SYS$GETDVI (0, 0, &dsc, &itmlst[0], &iosb, 0, 0, 0);
- >
- > The $DESCRIPTOR syntax only takes literal character array and not a Class
- > strings. If I create a subroutine to call the system service by passing a
- > literal character array, that works fine. However, if I pass a string object,
- > then the $DESCRIPTOR fails.
- >
- > Would it be wise to create a descriptor class which is derived from a string
- > class? From what I've been reading in "Effective C++" by Meyers the derived
- > class "isa" base class. So, the derived descriptor should really be a string,
- > but that doesn't seem to fit. Perhaps the descriptor class should contain a
- > member function which returns the proper descriptor. Or perhaps I shouldn't
- > use the DEC provided descrip.h at all and create a new structure based upon
- > the string class.
- >
- > Any thoughts about what is good and proper?
- >
- > Donald G. Plugge
- >
- > ac@n
- >
-
- Really, the best thing to do (IMHO) is to hide the dsc$descriptor_s class (a
- struct is a class) in a class as an "attribute" (data member) of another
- class. This way you (the author of the class) have complete control over the
- interface and implementation of the class. You could actually store a
- pointer to the descriptor if you wanted better implementation hiding (that
- way, the user of the class doesn't even have to know descriptors even exist).
-
- I say this from some experience. I am currently working on OpenVMS also
- (currently VAX, but expect to move to Alpha soon). I have tried several
- designs. The first was so awful, I'm embarrassed to admit it: I used
- multiple inheritance deriving from String _and_ dsc$descriptor - yuk! I also
- tried inheriting privately from dsc$descriptor_s. This was also a bad
- design, but it took longer to see why.
-
- Also, In this case I think a type cast to dsc$descriptor& is appropriate
- here:
-
- class FixedStringDescriptor
- {
- // Attribute:
-
- dsc$descriptor_s Descriptor;
- public:
-
- // Initialization:
-
- FixedStringDescriptor() {/*...*/}
-
- //...
-
- // Operations:
-
- operator const dsc$descriptor_s&() {return Descriptor;}
-
- //...
- };
-
- so that you can pass a FixedStringDescriptor object directly to a system
- service call with the argument coded as "const dsc$descriptor&" (I write my
- own prototypes for VMS system service calls. The ones DEC provides use "..."
- so are not type-safe). Some OO experts dislike user-defined type casts, but
- I this one seems justified.
-
- Note that casting to _const_ dsc$descriptor_s& is not as restrictive as it
- might seem at first. The users can still modify the data pointed to by
- dsc$a_pointer, they just cannot modify the pointer itself (nor any other
- dsc$descriptor_s members).
-
- I currently have an implemenation of FixedStringDescriptor that solves what
- you are trying to do that I can send you if you are interested. It is
- patterned after the STL (Standard Template Library) vector class.
- Interfacing with the String class is indirect, but fairly straight forward.
- We have a string class that we use after bad experiences with the DEC String
- class (e.g., my version corrupts the heap if you read from an istream to and
- emtpy String). So, I provide constructors from const char* rather than
- providing a constructor form (possibly more than one) string classes. Of
- course, allocation is handled "automatically" (as Alexander Stepanov, the
- author of the STL likes to say). For whatever reason, I decided to implement
- the entire class inline, so the aforementioned implementation hiding is not
- done.
-
- To answer the broader question, I think what all of this has taught me about
- OO design, is that sometimes you have to think about things a little deeper.
- It is indeed tempting to think of a descriptor-ized string as a type of
- string, but actually the two are quite different. A C++ string class is
- dynamic, whereas, a fixed-string descriptor is really just a fixed-length
- buffer. Also, I think deriving from a general purpose "utility" class (one
- that is not primarily intended for derivation) is usually not a good idea.
- There are no virtual functions to override, so there's little to be gained.
- Reading "Thinking in C++" by Bruce Eckel helped me to see the problem with
- private inheritance. He says the desire to do this ususally indicates an
- implementation that should be hidden.
-
- Hope this helps.
-
- Bruce Visscher
-
-